package migrations

import (
	"github.com/go-viper/mapstructure/v2"
	"github.com/pocketbase/pocketbase/core"
	m "github.com/pocketbase/pocketbase/migrations"
)

func init() {
	m.Register(func(app core.App) error {
		tracer := NewTracer("v0.4.6")
		tracer.Printf("go ...")

		// adapt to new workflow data structure
		{
			walker := &mWorkflowGraphWalker{}
			walker.Define(func(node *mWorkflowNode) (_changed bool, _err error) {
				_changed = false
				_err = nil

				if node.Type != "bizDeploy" {
					return
				}

				if node.Data == nil {
					return
				}

				if _, ok := node.Data["config"]; ok {
					nodeCfg := node.Data["config"].(map[string]any)

					provider := nodeCfg["provider"]
					switch provider {
					case "1panel-site":
						{
							if nodeCfg["providerConfig"] != nil {
								providerCfg := nodeCfg["providerConfig"].(map[string]any)
								if providerCfg["websiteId"] != nil && providerCfg["websiteId"].(string) != "" {
									providerCfg["websiteMatchPattern"] = "specified"
									nodeCfg["providerConfig"] = providerCfg

									node.Data["config"] = nodeCfg
									_changed = true
									return
								}
							}
						}

					case "baotapanel-site":
						{
							if nodeCfg["providerConfig"] != nil {
								providerCfg := nodeCfg["providerConfig"].(map[string]any)
								if providerCfg["siteType"] == nil || providerCfg["siteType"].(string) == "other" {
									providerCfg["siteType"] = "any"
									nodeCfg["providerConfig"] = providerCfg

									node.Data["config"] = nodeCfg
									_changed = true
								}
								if providerCfg["siteNames"] == nil || providerCfg["siteNames"].(string) == "" {
									providerCfg["siteNames"] = providerCfg["siteName"]
									delete(providerCfg, "siteName")
									nodeCfg["providerConfig"] = providerCfg

									node.Data["config"] = nodeCfg
									_changed = true
								}

								if _changed {
									return
								}
							}
						}

					case "baotapanelgo-site":
						{
							if nodeCfg["providerConfig"] != nil {
								providerCfg := nodeCfg["providerConfig"].(map[string]any)
								if providerCfg["siteNames"] == nil || providerCfg["siteNames"].(string) == "" {
									providerCfg["siteType"] = "php"
									providerCfg["siteNames"] = providerCfg["siteName"]
									delete(providerCfg, "siteName")
									nodeCfg["providerConfig"] = providerCfg

									node.Data["config"] = nodeCfg
									_changed = true
									return
								}
							}
						}

					case "baotawaf-site":
						{
							if nodeCfg["providerConfig"] != nil {
								providerCfg := nodeCfg["providerConfig"].(map[string]any)
								if providerCfg["siteNames"] == nil || providerCfg["siteNames"].(string) == "" {
									providerCfg["siteNames"] = providerCfg["siteName"]
									delete(providerCfg, "siteName")
									nodeCfg["providerConfig"] = providerCfg

									node.Data["config"] = nodeCfg
									_changed = true
									return
								}
							}
						}

					case "ratpanel-site":
						{
							if nodeCfg["providerConfig"] != nil {
								providerCfg := nodeCfg["providerConfig"].(map[string]any)
								if providerCfg["siteNames"] == nil || providerCfg["siteNames"].(string) == "" {
									providerCfg["siteNames"] = providerCfg["siteName"]
									delete(providerCfg, "siteName")
									nodeCfg["providerConfig"] = providerCfg

									node.Data["config"] = nodeCfg
									_changed = true
									return
								}
							}
						}

					case "safeline":
						{
							nodeCfg["provider"] = "safeline-site"

							node.Data["config"] = nodeCfg
							_changed = true
							return
						}
					}
				}

				return
			})

			// update collection `workflow`
			//   - migrate field `graphDraft` / `graphContent`
			{
				collection, err := app.FindCollectionByNameOrId("tovyif5ax6j62ur")
				if err != nil {
					return err
				}

				records, err := app.FindAllRecords(collection)
				if err != nil {
					return err
				}

				for _, record := range records {
					changed := false

					if record.GetRaw("graphDraft") != nil {
						graph := make(map[string]any)
						if err := record.UnmarshalJSONField("graphDraft", &graph); err != nil {
							return err
						}

						if _, ok := graph["nodes"]; ok {
							nodes := make([]*mWorkflowNode, 0)
							if err := mapstructure.Decode(graph["nodes"], &nodes); err != nil {
								return err
							}

							nodesChanged, err := walker.Visit(nodes)
							if err != nil {
								return err
							} else if nodesChanged {
								graph["nodes"] = nodes
								record.Set("graphDraft", graph)
								changed = true
							}
						}
					}

					if record.GetRaw("graphContent") != nil {
						graph := make(map[string]any)
						if err := record.UnmarshalJSONField("graphContent", &graph); err != nil {
							return err
						}

						if _, ok := graph["nodes"]; ok {
							nodes := make([]*mWorkflowNode, 0)
							if err := mapstructure.Decode(graph["nodes"], &nodes); err != nil {
								return err
							}

							nodesChanged, err := walker.Visit(nodes)
							if err != nil {
								return err
							} else if nodesChanged {
								graph["nodes"] = nodes
								record.Set("graphContent", graph)
								changed = true
							}
						}
					}

					if changed {
						if err := app.Save(record); err != nil {
							return err
						}

						tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
					}
				}
			}

			// update collection `workflow_run`
			//   - migrate field `graph`
			{
				collection, err := app.FindCollectionByNameOrId("qjp8lygssgwyqyz")
				if err != nil {
					return err
				}

				records, err := app.FindAllRecords(collection)
				if err != nil {
					return err
				}

				for _, record := range records {
					changed := false

					if record.GetRaw("graph") != nil {
						graph := make(map[string]any)
						if err := record.UnmarshalJSONField("graph", &graph); err != nil {
							return err
						}

						if _, ok := graph["nodes"]; ok {
							nodes := make([]*mWorkflowNode, 0)
							if err := mapstructure.Decode(graph["nodes"], &nodes); err != nil {
								return err
							}

							nodesChanged, err := walker.Visit(nodes)
							if err != nil {
								return err
							} else if nodesChanged {
								graph["nodes"] = nodes
								record.Set("graph", graph)
								changed = true
							}
						}
					}

					if changed {
						if err := app.Save(record); err != nil {
							return err
						}

						tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
					}
				}
			}

			// update collection `workflow_output`
			//   - migrate field `nodeConfig`
			{
				if _, err := app.DB().NewQuery("UPDATE workflow_output SET nodeConfig = REPLACE(nodeConfig, '\"provider\":\"safeline\"', '\"provider\":\"safeline-site\"') WHERE nodeConfig LIKE '%\"provider\":\"safeline\"%'").Execute(); err != nil {
					return err
				}

				if _, err := app.DB().NewQuery("UPDATE workflow_output SET nodeConfig = REPLACE(nodeConfig, '\"siteName\":', '\"siteNames\":')").Execute(); err != nil {
					return err
				}
			}
		}

		tracer.Printf("done")
		return nil
	}, func(app core.App) error {
		return nil
	})
}
